package sample.mybatis.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.github.pagehelper.Page;
import mybatis.testDemo.sqlProvider.SqlProvider;
import org.apache.ibatis.annotations.*;
import org.assertj.core.util.Maps;
import sample.mybatis.annotation.*;
import sample.mybatis.domain.User;
import sample.mybatis.dto.CustomDto;
import sample.mybatis.dto.UserDto;
import sample.mybatis.dto.UsersTmpDto;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Mapper
public interface MapperInterface extends BaseMapper<User>  {
    public  List<Map> selectListMap();
    public Integer getId();
    public String getName(@Param("name") String hcj1_);
    public int deleteById1();


    @Select("select * from users where #{sql}")
    public List<UsersTmpDto> select1(@Param("sql")boolean sql);
    @Select("${sql}")
    public UsersTmpDto select2(@Param("sql")String sql);
    @Select(value = "<script>select * from users where   <if test=\"name==name1\">name='hcj2 '</if></script>")
    public List<UsersTmpDto> selectCondition(@Param(value = "name") String name,@Param(value = "name1") String name1);
    @Select(value = "<script>select * from users where   <if test=\"name==1\">name='hcj2 '</if></script>")
    public List<UsersTmpDto> selectCondition3(@Param(value = "name") String name);
    @Select(value = "select * from users where name like concat('%',#{name},'%' )")
    public List<UsersTmpDto> selectCondition2(@Param(value = "name") String name);

    @Select("<script>         select * from users where\n" +
            "        <foreach collection=\"list\"  item=\"it\"  >\n" +
            "            <foreach collection=\"it.list\" item=\"it2\" separator=\"or\">\n" +
            "                (user_group_id= #{it.key}  and id=#{it2})\n" +
            "            </foreach>\n" +
            "        </foreach>     </script>")
    public List<Map<String,Object>> select3(@Param("list")ArrayList<CustomDto> list);
    @Select("<script>               select * from users where\n" +
            "        <foreach collection=\"map.entrySet()\"  index=\"key\" item=\"it\"  >\n" +
            "            <foreach collection=\"it\" item=\"it2\" separator=\"or\">\n" +
            "                ( user_group_id= #{key}  and id=#{it2})\n" +
            "            </foreach>\n" +
            "        </foreach> </script>")
    public List<Map<String,Object>> select(@Param("map")Map<Integer, ArrayList<Integer>> map);


    @Update(value = "<script>update users set user_group_name='党员<if test=\"count==3\">2</if><if test=\"count!=3\">${count}</if>' where id=#{count}</script>")
    public void outerUpdate(@Param(value = "count") int count);
    @Update(value = "<script>update users set name='hcj<if test=\"count==3\">2</if><if test=\"count!=3\">${count}</if>' where id=#{count}</script>")
    public void nestUpdate(@Param(value = "count") int count);

    public void checkNull(Map params);
    String trimParam(@Param("name") String name);

    String select5();
    List<String> select6(@Param("array") Integer[] array);

    String cDDATATag();

    String invokeStaticMethod(@Param("name") String name);

    @Select(value = "select username from users_1 where" +
            " id=#{map.val}  and id1=#{map.val2}")
    List<String> queryWithMap(@Param("map") HashMap<String, Object> hashMap);

    String testSqlInject(@Param("id")String id);


    interface NestClass {
        @SelectProvider(value = NestBuilder.class, method = "getSql")
        public String getSql();

        @SelectProvider(value = StaticNestBuilder.class, method = "getSqlWithStaticProvidr")
        public String getSqlWithStaticProvidr();
    }

    static class StaticNestBuilder {
        public static String getSqlWithStaticProvidr() {
            return "hello hcjgetSqlWithStaticProvidr";
        }
    }

    class NestBuilder {
        public MapperInterface sqlProviderTest;

        public NestBuilder() {
        }

        public NestBuilder(MapperInterface sqlProviderTestNew) {
            this.sqlProviderTest = sqlProviderTestNew;
        }

        public String getSql() {
            Maps.newHashMap("","").put("","");;
            return "hello hcj";
        }


    }
    class NestProvider{
        public String getSql(@Param("val") Integer val) {
            return "select name from users where id=#{val}";
        }
        public String countSql(@Param("val") Integer val){
            return "select count(1) from ("+getSql(val)+") aaa";
        };
    }
    @SelectProvider(method ="getSql" , type = SqlProvider.class)
    public void find2(@Param("val")String val);

    @SelectProvider(method ="getSql" , type = NestProvider.class)
    public String find(@Param("val")Integer val);
    @SelectProvider(method ="countSql" , type = NestProvider.class)
    public int count(@Param("val")Integer val);


    @SelectProvider(method ="getSqlProperties" , type = SqlProvider.class)
    public void findProperties(@Param("val")String val);
    /**
     * mock dataSource
     */
    @SqlCheck
    @Insert(value = "<script>" +
            " insert into users_1(id,username) \n" +
            "        <foreach collection=\"userDtoList\"  open=\"values\" separator=\",\" item=\"userDto\">\n" +
            " (#{userDto.id,jdbcType=VARCHAR},            #{userDto.username,jdbcType=VARCHAR}\n)" +
            "        </foreach>" +
            "</script>")
    public void insertList(@Param("userDtoList") List<UserDto> userDtoList);

    // <bind name="a" value=""/> +  ognl test

    @Select(value = "<script>" +
            "<bind name=\"a\" value=\"@mybatis.parser.Parser$ItemType@A.getValue()\"/> " +
            "select * from users where <if test=\"count==111\">count=#{a,jdbcType=VARCHAR}</if><if test=\"count==222\">count=222</if>" +
            "</script>")
    public List<String> query(@Param("count")Integer count);
    /**
     Integer.class , 如何 确认。
     * @param count
     * @param count1
     */
    @ROLE2
    public List<String> queryWithoutParamAnnotationInXML(String count, String count1);
    @Select(value = "<script>" +
            "<bind name=\"a\" value=\"@mybatis.parser.Parser$ItemType@A.getValue()\"/> " +
            "select * from users where <if test=\"count==111\">count=#{a,jdbcType=VARCHAR}</if><if test=\"count==222\">count=222</if>" +
            "</script>")
    public List<String> queryWithoutParamAnnotation(@Param("count") String count);

    @ROLE2
    public List<String> queryWithParamAnnotationInXML(@Param("count") String count);

    @Select(value = "<script>" +
            "select * from users" +
            "</script>")
    public List<String> queryNoClause();
    @Select(value = "<script>" +
            "select * from users where id=#{val} and id1=#{val2}" +
            "</script>")
    public List<String> queryWithPrimitive(int val,Integer val2);

    @ROLE1
    @Select(value = "<script>" +
            "select username from users_1" +
            "</script>")
    public Page<String> queryNoClauseWithPageAndRole1();


    @ROLE2
    @Select(value = "<script>" +
            "select username from users_1 where id=#{val} and id1=#{val2}" +
            "</script>")
    public Page<String> queryNoClauseWithPageAndRole2AndTwoParam(@Param(value = "val")String val,
                                                                 @Param(value = "val2")String val2);
    @ROLE2
    @Select(value = "<script>" +
            "select username from users_1 where id=#{val} and id1=#{val2}" +
            "</script>")
    public Page<String> queryWithPageAndRole2AndMap( Map<String,Object> map);
    /**
     * foreach.
     */
    @ROLE2
    @Select(value = "<script>" +
            "select username from users_1 where " +
            "        <foreach collection=\"list1\"  item=\"l\">\n" +
            "            id=#{l,jdbcType=VARCHAR} and id1=#{l,jdbcType=VARCHAR}\n" +
            "        </foreach>" +
            "</script>")
    public Page<String> queryWithPageAndRole2AndList(@Param(value = "list1") List list);


    @Select(value = "select * from test;")
    public List<Map<String,String>> queryInPg();
    /**
     todo 转义 =》  ?
     */
    @Select(value = "<script>" +
            " select jsonbs,id,jsonbs->'array',jsonbs->'subobj'->'subKey',jsonbs @> '{\"key\":\"val1\"}', " +
            " jsonbs @> '{\"grant_type\":\"admin\"}'" +
            " ,jsonbs ?? 'grant_type'" +
            " from public.test;" +
            "</script>")
    public List<Map<String,String>> queryJsonBInPg(@Param("val") int val);

    @Delete("TRUNCATE users;")
    void truncate();

    @Delete("TRUNCATE users_plus;")
    void truncateForPlus();
    /** for pluginUnionTest */
    @Delete("TRUNCATE users_1;")
    void truncateForPlugin();
    /** for tkTest */
    @Delete("TRUNCATE user_temp;")
    void truncateForTk();



    @EnablePg
    @Select(value = "select count(1)>0 from users where id=1 and user_group_name='党员1' ;")
    public boolean findSomeThings();

    @EnablePg
    @Select(value = "select * from users ")
    public List<UsersTmpDto> findObject();

    @EnablePg
    @Select(value = "select * from users ")
    public List<Map> findObject2();


    public int insertSqlMultiply();
    @Insert(value = "INSERT INTO \"public\".\"users\"(\"id\", \"user_group_id\", \"name\", \"age\", \"create_time\", \"money\", " +
            "\"user_account_id\", \"user_group_name\") " +
            "VALUES (#{usersTmpDto.id,jdbcType=INTEGER}, #{usersTmpDto.userGroupId,jdbcType=INTEGER}, #{usersTmpDto.name}, NULL, '2020-10-21 11:41:09.278063', 1.00, NULL, NULL);")
    public int insertSql(@Param(value = "usersTmpDto") UsersTmpDto usersTmpDto);

    @EnableMysql
    @Select(value = "select count(1)>0 from users where id=1;")
    public boolean findSomeThingsForMysql();

    @Select(value = "select count(1)>0 from users where id=3 and name='hcj 3'\n" +
            "union all\n" +
            "select count(1)>0 from users where id<3 and name in ('hcj 1','hcj 2') ;")
    List<Boolean> findAnotherThings();
}
